package com.tianji.remark.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.dto.remark.LikedTimesDTO;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.remark.constants.RedisConstants;
import com.tianji.remark.domain.dto.LikeRecordFormDTO;

import com.tianji.remark.domain.po.LikedRecord;
import com.tianji.remark.mapper.LikedRecordMapper;
import com.tianji.remark.service.ILikedRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * redis实现点赞
 * </p>
 *
 * @author taohongrun
 * @since 2025/2/10
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class RedisLikedRecordService extends ServiceImpl<LikedRecordMapper, LikedRecord> implements ILikedRecordService {
   private final StringRedisTemplate redisTemplate;
   private final RabbitTemplate rabbitTemplate;
   private final LikedStatServiceImpl likedStatService;

   @Override
   public void likeOrUnlike(LikeRecordFormDTO formDTO) {
       String remarkKey = remarkKey(formDTO.getBizId());
       String remarkSizeKey = remarkSizeKey(formDTO.getBizType());
       // 1.获取登录用户
       Long userId = UserContext.getUser();
       // 2.点赞或取消点赞
       boolean success = formDTO.getLiked() ? like(formDTO, userId) : unlike(formDTO, userId);
       if (!success) {
           return;
       }
       // 3.更新点赞数量
       //3.1统计点赞数量
       Long likedTimes = redisTemplate.opsForSet().size(remarkKey);
       if (likedTimes == null) {
           return;
       }
       //3.2更新点赞数量
        redisTemplate.opsForZSet().add(remarkSizeKey, formDTO.getBizId().toString(), likedTimes);
   }

    private boolean unlike(LikeRecordFormDTO formDTO, Long userId) {
        String key = remarkKey(formDTO.getBizId());
        Long remove = redisTemplate.opsForSet().remove(key, userId.toString());
        return remove != null && remove > 0;
    }

    private boolean like(LikeRecordFormDTO formDTO, Long userId) {
        String key = remarkKey(formDTO.getBizId());
        Long result = redisTemplate.opsForSet().add(key, userId.toString());
        return result != null && result > 0;
    }

    @Override
    public Set<Long> isBizLiked(List<Long> bizIds) {
       Set<Long> idSet = new HashSet<>();
      for (Long bizId : bizIds){
          String key = remarkKey(bizId);
          if (Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, UserContext.getUser().toString()))){
              idSet.add(bizId);
          }
      }
      return idSet;
    }

    @Override
    public void readLikedTimesAndSendMessage(String bizType, int maxBizSize) {
        // 1.读取并移除Redis中缓存的点赞总数
        String key = remarkSizeKey(bizType);
        Set<ZSetOperations.TypedTuple<String>> tuples = redisTemplate.opsForZSet().popMin(key, maxBizSize);
        if (CollUtils.isEmpty(tuples)) {
            return;
        }
        // 2.数据转换
        List<LikedTimesDTO> list = new ArrayList<>();
        for (ZSetOperations.TypedTuple<String> tuple : tuples) {
            String bizId = tuple.getValue();
            Double likedTimes = tuple.getScore();
            if (bizId == null || likedTimes == null) {
                continue;
            }
            list.add(LikedTimesDTO.of(Long.valueOf(bizId), likedTimes.intValue()));
        }
        // 3.批量修改点赞数量
        likedStatService.updateLikedTimesBatch(bizType, list);
    }

    private String remarkKey(Long bizId){
        return RedisConstants.LIKE_BIZ_KEY_PREFIX + bizId;
    }
    private String remarkSizeKey(String bizType){
        return RedisConstants.LIKE_COUNT_KEY_PREFIX + bizType;
    }
}
